package com.example.codeger.jimmer;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.NamingCase;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.meta.Column;
import cn.hutool.db.meta.MetaUtil;
import cn.hutool.db.meta.Table;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateEngine;
import com.example.codeger.DataSouseHandle;
import com.example.config.BeetlIntegrationExample;
import com.example.config.Jdbc2Java;
import gg.jte.CodeResolver;
import gg.jte.ContentType;
import gg.jte.TemplateOutput;
import gg.jte.output.StringOutput;
import gg.jte.resolve.ResourceCodeResolver;
import lombok.Builder;
import lombok.Data;
import org.springframework.lang.NonNull;

import javax.sql.DataSource;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 表 生成jimmer实体
 */
@Builder
@Data
public class JimmerEntitySourceBuilder {

    private final static String outFileNameDef = "outFileNamedef.java";
    private final static String outFilePathDef = "output/directory/";
    //模板文件路径地址
    @NonNull
    private String templateFilePath;
    //包名
    @NotNull(message = "basePackage不能空")
    private String basePackage;
    //要生成的表
    @NotEmpty(message = "tables要生成的表不能空")
    private List<String> tables;
    //是否生成关联表映射
    private boolean mappingFlag;
    //数据
    //private JimmerEntitySourceData data;

    private DataSource dataSource;

    @Data
    public static class JimmerEntitySourceData {
        //导入包
        List<String> imports = CollUtil.newArrayList();
        //基础包名
        @NotNull
        String packages_v;

        @NotNull
        String tableName;
        @NotNull
        String className;
        //表信息
        @NotNull
        Table tableInfo;


    }

    private JimmerEntitySourceData createJimmerEntitySourceData(Table tableMeta) {
        //准备数据
        JimmerEntitySourceData jimmerEntitySourceData = new JimmerEntitySourceData();
        jimmerEntitySourceData.setPackages_v(this.basePackage);
        //jimmerEntitySourceData.setCatalog(tableMeta.getCatalog());
        jimmerEntitySourceData.setTableName(tableMeta.getTableName());
        //表名字转 大驼峰 为类名
        jimmerEntitySourceData.setClassName(NamingCase.toPascalCase(tableMeta.getTableName()) + "Entity");
        jimmerEntitySourceData.setTableInfo(tableMeta);
        //需要导的包
        List<String> imports = jimmerEntitySourceData.getImports();
        for (Column column : tableMeta.getColumns()) {
            Jdbc2Java.Jdbc2JavaEnum.getJdbc2JavaEnum(column.getTypeEnum()).getJavaType();
            if (column.isNullable()) {
                if (!imports.contains("org.jetbrains.annotations.Nullable")) {
                    imports.add("org.jetbrains.annotations.Nullable");
                }
            }
            if (column.isPk()) {
                if (!imports.contains("org.babyfish.jimmer.sql.Id")) {
                    imports.add("org.babyfish.jimmer.sql.Id");
                }
            }
        }

        //添加jimmer必要的包
        imports.add("org.babyfish.jimmer.sql.Entity");
        imports.add("org.babyfish.jimmer.sql.Table");

        //对需要导的包 排序
        List<String> collect = imports.stream().sorted().collect(Collectors.toList());
        jimmerEntitySourceData.setImports(collect);

        return jimmerEntitySourceData;
    }

    public void handlerBeetl() throws SQLException {
        //获取模板引擎
        TemplateEngine engine = BeetlIntegrationExample.getTemplateEngine();

        // 获取模板
        Template template = engine.getTemplate(this.templateFilePath);

        if (dataSource == null) {
            dataSource = DataSouseHandle.createDataSource();
        }

        //循环处理每个表的
        for (String tableName : tables) {
            //数据库获取表信息
            Table tableMeta = MetaUtil.getTableMeta(dataSource, tableName);
            if (tableMeta == null) {
                throw new RuntimeException(tableName + "没找到");
            }

            JimmerEntitySourceData jimmerEntitySourceData = createJimmerEntitySourceData(tableMeta);

            // 渲染模板
            String result = template.render(BeanUtil.beanToMap(jimmerEntitySourceData));
            // 输出结果到控制台
            System.out.println(result);
            //输出到文件
            outToFile(basePackage, jimmerEntitySourceData.getClassName(), result);
        }

    }


    public void handlerJte() throws SQLException {

        CodeResolver codeResolver = new ResourceCodeResolver("templates"); // This is the directory where your .jte files are located.
        gg.jte.TemplateEngine templateEngine = gg.jte.TemplateEngine.create(codeResolver, ContentType.Plain);
        TemplateOutput output = new StringOutput();

        if (dataSource == null) {
            dataSource = DataSouseHandle.createDataSource();
        }
        //循环处理每个表的
        for (String tableName : tables) {
            //数据库获取表信息
            Table tableMeta = MetaUtil.getTableMeta(dataSource, tableName);
            if (tableMeta == null) {
                throw new RuntimeException(tableName + "没找到");
            }

            //构建数据
            JimmerEntitySourceData jimmerEntitySourceData = createJimmerEntitySourceData(tableMeta);

            // 渲染模板 相对路径的
            templateEngine.render("jimmer/entity.jte", jimmerEntitySourceData, output);

            // 输出结果到控制台
            System.out.println(output.toString());
            //输出到文件
            outToFile(basePackage, jimmerEntitySourceData.getClassName(), output.toString());
        }

    }

    /**
     * 将渲染后的内容输出到文件中
     *
     * @param basePackage 包路径
     * @param className   类名
     * @param result      内容
     */
    private static void outToFile(String basePackage, String className, String result) {
        // 指定输出文件路径 这样会输出到 target/test-classes下
        //输出的文件路径 /结尾
        String outFilePath = StrUtil.replace(basePackage, ".", File.separator);
        if (!StrUtil.endWith(outFilePath, File.separator)) {
            outFilePath = outFilePath + File.separator;
        }
        //输出的文件名 带后缀
        String outFileName = className + ".java";
        String filePath = outFilePath + (StrUtil.isBlank(outFileName) ? outFileNameDef : outFileName);
        // 使用 Hutool 的 FileUtil 将内容写入文件
        FileUtil.writeUtf8String(result, filePath);
    }
}